#include <iostream>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <fcntl.h>
#include <cerrno>
using namespace std;

// 读缓冲区大小
const int BUFFER_SIZE = 4096;

// 主状态机
enum CHECK_STATE{
  CHECK_STATE_REQUESTLINE = 0,
  CHECK_STATE_HEADER,
};
// 从状态机
enum LINE_STATUS {
  LINE_OK = 0,
  LINE_BAD,
  LINE_OPEN,
};
// HTTP请求结果
enum HTTP_CODE {
  NO_REQUEST,
  GET_REQUEST,
  BAD_REQUEST,
  FORBIDDEN_REQUEST,
  INTERNAL_ERROR,
  CLOSED_CONNECTION,
};
// 处理结果
static const char* szret[] = {
  "I get a correct result\n",
  "Something wrong\n"
};

// 解析行内容
LINE_STATUS parse_line(char* buffer, int& checked_index, int& read_index) {
  char temp;
  // checked_index是当前正在检查的字符位置
  // read_index是缓冲区中已读的字符数
  // checked_index和read_index之间的字符是未检查的
  for (; checked_index < read_index; ++checked_index) {
    // 当前分析的字符
    temp = buffer[checked_index];
    // 如果当前字符是'\r'，则可能读取到一个完整的行
    if (temp == '\r') {
      // 下一个位置就是读取的位置，说明还没读完这一行
      if ((checked_index + 1) == read_index) {
        return LINE_OPEN;
      
      } // 如果下一个字符是'\n'，则读取到一个完整的行
      else if (buffer[checked_index + 1] == '\n') {
        buffer[checked_index++] = '\0';
        buffer[checked_index++] = '\0';
        return LINE_OK;
      }
      // 不是上面两种情况的话那就只有出错了
      return LINE_BAD;
    } 
    else if (temp == '\n') {
      if ((checked_index > 0) && (buffer[checked_index - 1] == '\r')) {
        buffer[checked_index - 1] = '\0';
        buffer[checked_index++] = '\0';
        return LINE_OK;
      } 

      return LINE_BAD;
    }
  }
  return LINE_OPEN;
}

// 解析HTTP请求行
HTTP_CODE parse_requestline(char* temp, CHECK_STATE& check_state) {
  char* url = strpbrk(temp, " \t");
  if (!url) {
    return BAD_REQUEST;
  }
  *url++ = '\0';
  
  char* method = temp;
  if (strcasecmp(method, "GET") == 0) {
    // 处理GET请求
    cout << "Request method: GET" << endl;
  } 
  else {
    return BAD_REQUEST;
  }

  // 跳过空格
  while (*url == ' ' || *url == '\t') {
    ++url;
  }

  char* version = strpbrk(url, " \t");
  if (!version) {
    return BAD_REQUEST;
  }
  *version++ = '\0';
  version += strspn(version, " \t"); // 跳过空格
  // 检查HTTP版本
  if (strcasecmp(version, "HTTP/1.1") != 0) {
    return BAD_REQUEST;
  }
  // 检查URL是否合法
  if (strncasecmp(url, "http://", 7) == 0) {
    url += 7; // 跳过"http://"
    url = strchr(url, '/'); // 查找路径开始的位置
  }
  if (!url || url[0] != '/') {
    return BAD_REQUEST; // URL必须以'/'开头
  }
  cout << "Request URL: " << url << endl;

  check_state = CHECK_STATE_HEADER; // 切换到头部解析状态
  return NO_REQUEST; // 返回成功状态
}

// 解析HTTP请求头
HTTP_CODE parse_headers(char* temp) {
  // 如果遇到空行，说明头部解析结束
  if (temp[0] == '\0') {
    return GET_REQUEST; // 返回GET请求状态
  }
  else if (strncasecmp(temp, "Host:", 5) == 0) {
    // 处理Host头部
    char* host = temp + 5;
    while (*host == ' ' || *host == '\t') {
      ++host; // 跳过空格
    }
    cout << "Host: " << host << endl;
  } 
  else if (strncasecmp(temp, "Connection:", 11) == 0) {
    // 处理Connection头部
    char* connection = temp + 11;
    while (*connection == ' ' || *connection == '\t') {
      ++connection; // 跳过空格
    }
    cout << "Connection: " << connection << endl;
  } 
  else {
    cout << "I can not handle this header: " << endl; // 输出未知头部
  }
  return NO_REQUEST; // 返回未完成请求状态
}

// 解析HTTP请求入口的函数
HTTP_CODE parse_content (char* buffer, int& checked_index, int& read_index, 
                          CHECK_STATE& check_state, int& start_line) {
  LINE_STATUS line_status = LINE_OK;
  HTTP_CODE ret = NO_REQUEST;

  while ((line_status = parse_line(buffer, checked_index, read_index)) == LINE_OK) {
    char* temp = buffer + start_line;
    start_line = checked_index; // 更新下一行的起始位置

    // 根据当前状态解析请求行或请求头
    switch (check_state) {
      case CHECK_STATE_REQUESTLINE:
      {
        ret = parse_requestline(temp, check_state);
        if (ret == BAD_REQUEST) {
          return BAD_REQUEST; // 请求行解析失败
        }
        break;
      }
      case CHECK_STATE_HEADER:
      {
        ret = parse_headers(temp);
        if (ret == GET_REQUEST) {
          return GET_REQUEST; // 完成GET请求
        } else if (ret == BAD_REQUEST) {
          return BAD_REQUEST; // 请求头解析失败
        }
        break;
      }
      default:
      {
        return INTERNAL_ERROR; // 内部错误
      }
    }
  }

  if (line_status == LINE_BAD) {
    return BAD_REQUEST; // 行格式错误
  }
  return NO_REQUEST; // 请求未完成
}


int main(int argc, char* argv[]) {
  if (argc <= 2) {
    cerr << "Usage: " << argv[0] << " <IP> <Port>" << endl;
    return 1;
  }
  const char* ip = argv[1];
  int port = atoi(argv[2]);

  struct sockaddr_in address;
  memset(&address, 0, sizeof(address));
  address.sin_family = AF_INET;
  inet_pton(AF_INET, ip, &address.sin_addr);
  address.sin_port = htons(port);

  int listenFd = socket(PF_INET, SOCK_STREAM, 0);
  assert(listenFd >= 0);

  int ret = bind(listenFd, (struct sockaddr*)&address, sizeof(address));
  assert(ret != -1);

  ret = listen(listenFd, 5);
  assert(ret != -1);

  struct sockaddr_in client;
  socklen_t clientLen = sizeof(client);
  int connFd = accept(listenFd, (struct sockaddr*)&client, &clientLen);
  if (connFd < 0) {
    cerr << "Accept failed: " << strerror(errno) << endl;
  }
  else{
    char buffer[BUFFER_SIZE]; // 读缓冲区
    memset(buffer, 0, BUFFER_SIZE);
    int data_read = 0;
    int read_index = 0; // 已读字符数
    int checked_index = 0; // 已检查字符数
    int start_line = 0; // 当前行的起始位置

    CHECK_STATE check_state = CHECK_STATE_REQUESTLINE; // 初始状态为请求行解析状态
    while(1){
      data_read = recv(connFd, buffer + read_index, BUFFER_SIZE - read_index, 0);
      if (data_read < 0) {
        cerr << "Read failed: " << strerror(errno) << endl;
        break;
      } 
      else if (data_read == 0) {
        cout << "Client closed connection." << endl;
        break; // 客户端关闭连接
      }
      read_index += data_read; // 更新已读字符数

      HTTP_CODE result = parse_content(buffer, checked_index, read_index, check_state, start_line);
      if (result == NO_REQUEST) {
        continue; // 请求未完成，继续读取
      } 
      else if (result == GET_REQUEST) {
        send(connFd, szret[0], strlen(szret[0]), 0); // 发送成功结果
        break; // 完成请求，退出循环
      } 
      else {
        send(connFd, szret[1], strlen(szret[1]), 0); // 发送错误结果
        break; // 出现错误，退出循环
      }
    }
    close(connFd); // 关闭连接
  }
  
  close(listenFd); // 关闭监听套接字
  return 0; // 程序结束
}